/**
 * Copyright (c) 2012-2014 All Rights Reserved.
 */
package com.easy.framwork.jdbc.query;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.easy.framwork.exceptions.IllegalArgException;

/**
 * 
 * @author wy
 * @version v 0.1 2014-1-3 下午12:21:10 wy Exp $
 */
public class Where {

    /** where condition sql */
    private final StringBuilder whereSQL;

    /** query param */
    private final List<Object> paramList;

    /**
     * 
     */
    public Where() {
        whereSQL = new StringBuilder();
        paramList = new ArrayList<Object>();
    }

    /**
     * 
     * 
     * @param wa
     * @return
     */
    public Where and(Where wa) {
        if (wa == this) {
            throw new IllegalArgException("can not add slef WhereAssembly");
        }

        whereSQL.append(" AND (").append(wa.getSQL()).append(" )");

        paramList.addAll(Arrays.asList(wa.getParams()));

        return this;
    }

    /**
     * 
     * 
     * @param wa
     * @return
     */
    public Where or(Where wa) {

        if (wa == this) {
            throw new IllegalArgException("can not add slef WhereAssembly");
        }

        whereSQL.append(" OR (").append(wa.getSQL()).append(" )");

        paramList.addAll(Arrays.asList(wa.getParams()));

        return this;
    }

    /**
     * and like
     * 
     * @param column
     * @param value
     * @return
     */
    public Where andLike(String column, Object value) {

        whereSQL.append(" AND ").append(column).append(" LIKE ").append("?");

        paramList.add(value);

        return this;
    }

    /**
     * or like
     * 
     * @param column
     * @param value
     * @return
     */
    public Where orLike(String column, Object value) {

        whereSQL.append(" OR ").append(column).append(" LIKE ").append("?");

        paramList.add(value);

        return this;
    }

    /**
     * and like
     * 
     * @param column
     * @param value
     * @return
     */
    public Where andContains(String column, Object value) {

        this.andLike(column, "%" + value + "%");
        return this;
    }

    /**
     * or like
     * 
     * @param column
     * @param value
     * @return
     */
    public Where orContains(String column, Object value) {

        this.orLike(column, "%" + value + "%");

        return this;
    }

    /**
     * and like
     * 
     * @param column
     * @param value
     * @return
     */
    public Where andBeginWith(String column, Object value) {

        this.andLike(column, value + "%");

        return this;
    }

    /**
     * or like
     * 
     * @param column
     * @param value
     * @return
     */
    public Where orBeginWith(String column, Object value) {

        this.orLike(column, value + "%");

        return this;
    }

    /**
     * and like
     * 
     * @param column
     * @param value
     * @return
     */
    public Where andEndWith(String column, Object value) {

        this.andLike(column, "%" + value);

        return this;
    }

    /**
     * or like
     * 
     * @param column
     * @param value
     * @return
     */
    public Where orEndWith(String column, Object value) {
        this.orLike(column, "%" + value);

        return this;
    }

    /**
     * and not like
     * 
     * @param column
     * @param value
     * @return
     */
    public Where andNotLike(String column, Object value) {

        whereSQL.append(" AND ").append(column).append(" NOT LIKE ").append("?");

        paramList.add(value);

        return this;
    }

    /**
     * or not like
     * 
     * @param column
     * @param value
     * @return
     */
    public Where orNotLike(String column, Object value) {

        whereSQL.append(" OR ").append(column).append(" not LIKE ").append("?");

        paramList.add(value);

        return this;
    }

    /**
     * and like
     * 
     * @param column
     * @param value
     * @return
     */
    public Where andNotContains(String column, Object value) {

        this.andNotLike(column, "%" + value + "%");
        return this;
    }

    /**
     * or like
     * 
     * @param column
     * @param value
     * @return
     */
    public Where orNotContains(String column, Object value) {

        this.orNotLike(column, "%" + value + "%");

        return this;
    }

    /**
     * and like
     * 
     * @param column
     * @param value
     * @return
     */
    public Where andNotBeginWith(String column, Object value) {

        this.andNotLike(column, value + "%");

        return this;
    }

    /**
     * or like
     * 
     * @param column
     * @param value
     * @return
     */
    public Where orNotBeginWith(String column, Object value) {

        this.orNotLike(column, value + "%");

        return this;
    }

    /**
     * and like
     * 
     * @param column
     * @param value
     * @return
     */
    public Where andNotEndWith(String column, Object value) {

        this.andNotLike(column, "%" + value);

        return this;
    }

    /**
     * or like
     * 
     * @param column
     * @param value
     * @return
     */
    public Where orNotEndWith(String column, Object value) {
        this.orNotLike(column, "%" + value);

        return this;
    }

    /**
     * and is null
     * 
     * @param column
     * @return
     */
    public Where andIsNull(String column) {

        whereSQL.append(" AND ").append(column).append(" IS NULL ");
        return this;
    }

    /**
     * or is null
     * 
     * @param column
     * @return
     */
    public Where orIsNull(String column) {

        whereSQL.append(" OR ").append(column).append(" IS NULL ");

        return this;
    }

    /**
     * and is null
     * 
     * @param column
     * @return
     */
    public Where andIsNotNull(String column) {

        whereSQL.append(" AND ").append(column).append(" IS NOT NULL ");
        return this;
    }

    /**
     * or is null
     * 
     * @param column
     * @return
     */
    public Where orIsNotNull(String column) {

        whereSQL.append(" OR ").append(column).append(" IS NOT NULL ");

        return this;
    }

    /**
     * and equals
     * 
     * @param column
     * @param value
     * @return
     */
    public Where andEq(String column, Object value) {

        whereSQL.append(" AND ").append(column).append("=").append("?");

        paramList.add(value);

        return this;
    }

    /**
     * or equals
     * 
     * @param column
     * @param value
     * @return
     */
    public Where orEq(String column, Object value) {

        whereSQL.append(" OR ").append(column).append("=").append("?");

        paramList.add(value);

        return this;
    }

    /**
     * and not equals
     * 
     * @param column
     * @param value
     * @return
     */
    public Where andNotEq(String column, Object value) {

        whereSQL.append(" AND ").append(column).append("!=").append("?");

        paramList.add(value);

        return this;
    }

    /**
     * or not equals
     * 
     * @param column
     * @param value
     * @return
     */
    public Where orNotEq(String column, Object value) {

        whereSQL.append(" OR ").append(column).append("!=").append("?");

        paramList.add(value);

        return this;
    }

    /**
     * and greater than
     * 
     * @param column
     * @param value
     * @return
     */
    public Where andGt(String column, Object value) {

        whereSQL.append(" AND ").append(column).append(">").append("?");

        paramList.add(value);

        return this;
    }

    /**
     * or greater than
     * 
     * @param column
     * @param value
     * @return
     */
    public Where orGt(String column, Object value) {

        whereSQL.append(" OR ").append(column).append(">").append("?");

        paramList.add(value);

        return this;
    }

    /**
     * and letter than
     * 
     * @param column
     * @param value
     * @return
     */
    public Where andLt(String column, Object value) {

        whereSQL.append(" AND ").append(column).append("<").append("?");

        paramList.add(value);

        return this;
    }

    /**
     * or letter than
     * 
     * @param column
     * @param value
     * @return
     */
    public Where orLt(String column, Object value) {

        whereSQL.append(" OR ").append(column).append("<").append("?");

        paramList.add(value);

        return this;
    }

    /**
     * and greater or equal than
     * 
     * @param column
     * @param value
     * @return
     */
    public Where andGte(String column, Object value) {

        whereSQL.append(" AND ").append(column).append(">=").append("?");

        paramList.add(value);

        return this;
    }

    /**
     * or greater or equal than
     * 
     * @param column
     * @param value
     * @return
     */
    public Where orGte(String column, Object value) {

        whereSQL.append(" OR ").append(column).append(">=").append("?");

        paramList.add(value);

        return this;
    }

    /**
     * and letter or equal than
     * 
     * @param column
     * @param value
     * @return
     */
    public Where andLte(String column, Object value) {

        whereSQL.append(" AND ").append(column).append("<=").append("?");

        paramList.add(value);

        return this;
    }

    /**
     * or letter or equal than
     * 
     * @param column
     * @param value
     * @return
     */
    public Where orLte(String column, Object value) {

        whereSQL.append(" OR ").append(column).append("<=").append("?");

        paramList.add(value);

        return this;
    }

    /**
     * bettwen
     * 
     * @param column
     * @param value1
     * @param value2
     * @return
     */
    public Where andBettwen(String column, Object value, Object other) {

        whereSQL.append(" AND (").append(column).append(" BETWEEN ").append("?").append(" AND ")
            .append("?").append(")");

        paramList.add(value);
        paramList.add(other);

        return this;
    }

    /**
     * bettwen
     * 
     * @param column
     * @param value1
     * @param value2
     * @return
     */
    public Where orBettwen(String column, Object value, Object other) {

        whereSQL.append(" OR (").append(column).append(" BETWEEN ").append("?").append(" AND ")
            .append("?").append(")");

        paramList.add(value);
        paramList.add(other);

        return this;
    }

    /**
     * 添加sql和参数
     * 
     * @param sql
     * @param params
     * @return
     */
    public Where append(String sql, Object... params) {
        whereSQL.append(sql);
        if (params != null && params.length > 0) {
            for (Object param : params) {
                paramList.add(param);
            }
        }
        return this;
    }

    /**
     * Getter method for property <tt>where</tt>.
     * 
     * @return where
     */
    public String getSQL() {

        String sql = whereSQL.toString().trim();
        if (sql.length() > 2 && sql.substring(0, 2).equalsIgnoreCase("OR")) {
            sql = sql.substring(2).trim();
        } else if (sql.length() > 3 && sql.substring(0, 3).equalsIgnoreCase("AND")) {
            sql = sql.substring(3).trim();
        }
        //remove
        if (sql.startsWith("(") && sql.endsWith(")")) {
            sql = sql.substring(1, sql.length() - 1);
        }
        return sql;
    }

    /**
     * Getter method for property <tt>getParams</tt>.
     * 
     * @return paramList
     */
    public Object[] getParams() {
        return paramList.toArray();
    }

}
